#include "bw_file_tool.h"
#include "bw_Str.h"
#include <stdbool.h>
//#include "bw_comm.h"
#include "bw_FcgiRequest.h"
using namespace std;

namespace bwcgi
{

bool Upg_File::checkMd5Value(string Md5Str, string fileName)
{
	string Md5 = getMd5Value(fileName);
	if(Md5.empty())
	{
		cgi_debug("get md5 error");
		return false;
	}
	//UPG_PRINT("actualMd5 = %s", Md5.c_str());
	return Md5.compare(Md5Str) == 0;
}

bool Upg_File::checkMd5Value(const char * Md5Str, const char * fileName)
{
	char Md5Buf[SZ_256B] = {0};
	bool ret = getMd5Value(fileName, Md5Buf, sizeof(Md5Buf));
	if(!ret)
	{
		cgi_debug("get Md5 error");
		return ret;
	}
	size_t cmpLen = strlen(Md5Buf);
    return strncmp(Md5Str, Md5Buf, cmpLen) == 0;
}

/*
 * 成功：返回md5值
 * 失败：返回string("")
 */
string Upg_File::getMd5Value(string fileName)
{
	string Md5 = "";
	if(!File_exists(fileName.c_str()))
	{
		cgi_debug("file not exist(%s)", fileName.c_str());
		return string("");
	}
	else
	{
		char cmd[CMD_LEN] = {0};
		char execBuf[SZ_1K] = {0};
		snprintf(cmd, CMD_LEN, "md5sum %s", fileName.c_str());
		//UPG_PRINT("cmd = %s", cmd);
		if(!File_Shell_exec(cmd, execBuf, sizeof(execBuf)))
			return string("");

		string execStr = execBuf;
		size_t md5Pos = execStr.find(fileName);
		if(string::npos != md5Pos)
		{
			Md5 = execStr.substr(0, md5Pos-2);
			cgi_debug("md5 = %s", Md5.c_str());
		}
	}
	return Md5;
}

/*
 * 成功：返回true
 * 失败：返回false
 */
bool Upg_File::getMd5Value(const char * fileName, char * Md5Buf, S32 bufLen)
{
	if(!File_exists(fileName))
	{
		cgi_debug("file not exist(%s)", fileName);
		return false;
	}

	else
	{
		char cmd[CMD_LEN] = {0};
		char execBuf[SZ_1K] = {0};
		snprintf(cmd, CMD_LEN, "md5sum %s", fileName);
		cgi_debug("cmd = %s", cmd);
		if(!File_Shell_exec(cmd, execBuf, sizeof(execBuf)))
			return false;
		
		string execStr = execBuf;
		size_t md5Pos = execStr.find(fileName);
		if(string::npos != md5Pos)
		{
			string Md5Str = execStr.substr(0, md5Pos-2);
			snprintf(Md5Buf, bufLen, "%s", Md5Str.c_str());
			cgi_debug("md5 = %s", Md5Buf);
			return true;
		}
		else
			return false;
	}

}

bool Upg_File::checkAndCreatePath(const char * filePath)
{
	if(nullptr == filePath)
	{
		cgi_debug("filePath is nullptr");
		return false;
	}
	
	bool ret = File_exists(filePath);
	if(ret)
	{
		ret = File_isPath(filePath);
		if(ret)
			return ret;
		else
		{
			cgi_debug("param exist, but not a path(%s)", filePath);
			return false;
		}
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "mkdir %s -vp", filePath);
	system(cmd);
	sync();

	return File_exists(filePath);
}

/*
 *	删除某个文件(文件名必须带有路径)
 */
bool Upg_File::deleteFile(const char * fileName)
{
	if(nullptr == fileName)
	{
		cgi_debug("fileName is nullptr");
		return false;
	}

	string fileNameStr = fileName;
	if(string::npos == fileNameStr.find('/'))
	{
		cgi_debug("fileName invalid(%s), should have path", fileName);
		return false;
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "rm %s* -f", fileName);
	system(cmd);
	sync();

    return !File_exists(fileName);

}

/*
 * 删除某个目录下的所有文件
 * exceptFile:如果有传参, 则除开exceptFile ,删除目录下的其他文件, exceptFile如果含有路径，则路径必须和filePath相同
 */
bool Upg_File::deleteAllFileInPath(const char * filePath, const char * exceptFile)
{
	bool ret;
	
	if(nullptr == filePath)
	{
		cgi_debug("filePath is nullptr");
		return false;
	}

	string filePathStr = filePath;
	if(filePathStr[filePathStr.size()-1] != '/')
	{
		filePathStr = filePathStr + '/';
	}
	ret = File_exists(filePathStr.c_str());
	if(!ret)
	{
		cgi_debug("filePath not exist");
		return ret;
	}
	
	if(nullptr == exceptFile)
	{
		char cmd[CMD_LEN] = {0};
		snprintf(cmd, CMD_LEN, "rm -rf %s*", filePathStr.c_str());
		cgi_debug("remove cmd : %s", cmd);
		system(cmd);
		sync();
		return true;
	}
	
	string exceptFileStr = exceptFile;
	if(exceptFileStr[exceptFileStr.size()-1] == '/')
		exceptFileStr = exceptFileStr.substr(0, exceptFileStr.size()-1);
	
	size_t fnamePos = exceptFileStr.rfind('/');
	if(string::npos != fnamePos)
	{
		if(0 != (exceptFileStr.substr(0, fnamePos+1).compare(filePathStr)))
		{
			cgi_debug("exceptFile invalid(%s), should not have same path", exceptFile);
			return false;
		}
		else
			exceptFileStr = exceptFileStr.substr(fnamePos+1);
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "ls %s | grep -v %s | xargs -i rm -rf %s{}", filePathStr.c_str(), exceptFileStr.c_str(), filePathStr.c_str());
	cgi_debug("remove cmd : %s", cmd);
	system(cmd);
	sync();

	return true;
}

/*
 * 拷贝文件到目的路径
 * fileName: 必须包含路径,可以是单个文件也可以是个文件夹; destPath: 拷贝的目的路径
 */
bool Upg_File::copyFile(const char * fileName, const char * destPath)
{
	if((nullptr == destPath) || (nullptr == fileName))
	{
		cgi_debug("Param is nullptr");
		return false;
	}

	bool ret;
	ret = File_exists(fileName);
	if( !ret )
	{
		cgi_debug("fileName not exist(%s)", fileName);
		return ret;
	}

	size_t filePos;
	string fileNameStr = fileName;
	filePos = fileNameStr.rfind('/');
	if(filePos == string::npos)
	{
		cgi_debug("fileName invaild(%s), should have path", fileName);
		return false;
	}
	string onlyName = fileNameStr.substr(filePos+1);

	string destPathStr = destPath;
	if(destPathStr[destPathStr.size()-1] != '/')
	{
		destPathStr = destPathStr + '/';
	}
	ret = checkAndCreatePath(destPathStr.c_str());
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}

	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "cp %s %s -r", fileName, destPathStr.c_str());
	cgi_debug("cp cmd : %s", cmd);
	system(cmd);
	sync();

	string destFile = destPathStr + onlyName;
	//UPG_PRINT("destFile = %s", destFile.c_str());
	return File_exists(destFile.c_str());
}

/*	功能：拷贝一个目录下的所有文件 到目的路径	*/
bool Upg_File::copyAllFileInPath(const char * srcPath, const char * destPath)
{
	if((nullptr == destPath) || (nullptr == srcPath))
	{
		cgi_debug("Param is nullptr");
		return false;
	}

	bool ret;
	string srcPathStr = srcPath;
	if(srcPathStr[srcPathStr.size()-1] != '/')
		srcPathStr = srcPathStr + '/';
	
	ret = File_isPath(srcPathStr.c_str());
	if( !ret )
	{
		cgi_debug("srcPath is not path(%s)", srcPathStr.c_str());
		return ret;
	}

	string destPathStr = destPath;
	if(destPathStr[destPathStr.size()-1] != '/')
	{
		destPathStr = destPathStr + '/';
	}
	ret = checkAndCreatePath(destPathStr.c_str());
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}

	vector<string>Array;
	ret = getAllFileInPath(srcPathStr.c_str(), Array);
	if(!ret)
	{
		cgi_debug("getAllFileInPath error: %s", srcPathStr.c_str());
		return false;
	}
	if(Array.empty())
	{
		cgi_debug("ERROR! FilePath has none files: %s", srcPathStr.c_str());
		return false;
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "cp %s* %s -r", srcPathStr.c_str(), destPathStr.c_str());
	cgi_debug("cp cmd : %s", cmd);
	system(cmd);
	sync();

	/* 检测拷贝过去的文件是否存在	*/
	string destFileName;
	for (const auto &i : Array) {
		destFileName.clear();
		destFileName = destPathStr + i;
		ret = File_exists(destFileName.c_str());
		if(!ret)
		{
			cgi_debug("Copy file error: %s", destFileName.c_str());
			return false;
		}
	}
	
	return true;
}

/*
 *	压缩文件(参数为含路径文件名)
 *	fileName: 需要压缩的文件或文件夹。
 *	outFileName:压缩后的文件名,必须以.tar.gz结尾
 */
bool Upg_File::tarFile(const char * fileName, const char * outFileName)
{
	size_t filePos;
	bool ret;
	if((nullptr == outFileName) || (nullptr == fileName))
	{
		cgi_debug("Param is nullptr");
		return false;
	}

	string fileNameStr = fileName;
	string outFileNameStr = outFileName;
	
	if(string::npos == outFileNameStr.rfind(".tar.gz"))
	{
		cgi_debug("outFileName invaild(%s), should end with (.tar.gz)", outFileName);
		return false;
	}

	ret = File_exists(fileName);
	if(!ret)
	{
		cgi_debug("file not exist(%s)", fileName);
		return ret;
	}

	filePos = outFileNameStr.rfind('/');
	if(string::npos == filePos)
	{
		cgi_debug("outFileName invalid(%s), should be full path", outFileNameStr.c_str());
		return false;
	}
	string tmpOutFile = TAR_TEMP_FILEPATH + outFileNameStr.substr(filePos+1);
	string OutPath = outFileNameStr.substr(0, filePos);
	cgi_debug("tmp file = %s, outpath = %s", tmpOutFile.c_str(), OutPath.c_str());
	
	filePos = fileNameStr.rfind('/');
	if(string::npos == filePos)
	{
		cgi_debug("fileName invalid(%s), should be full path", fileNameStr.c_str());
		return false;
	}

	ret = checkAndCreatePath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}
	
	ret = deleteAllFileInPath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("deleteAllFileInPath error");
		return ret;
	}

	ret = File_isPath(fileNameStr.c_str());
	if(!ret)
	{
		string FilePath = fileNameStr.substr(0, filePos+1);
		string onlyName = fileNameStr.substr(filePos+1);

		char cmd[CMD_LEN] = {0};
		snprintf(cmd, CMD_LEN, "%s %s -C %s %s", TAR_PRESS, tmpOutFile.c_str(), FilePath.c_str(), onlyName.c_str());
		cgi_debug("cmd = %s", cmd);
		system(cmd);
		sync();
	}
	else
	{
		vector <string> Files;
		ret = getAllFileInPath(fileNameStr.c_str(), Files);
		if(!ret)
		{
			cgi_debug("getAllFileInPath ERROR :%s", fileNameStr.c_str());
			return false;
		}

		char cmd[CMD_LEN] = {0};
		snprintf(cmd, CMD_LEN, "%s %s -C %s", TAR_PRESS, tmpOutFile.c_str(), fileNameStr.c_str());
		string cmdStr = cmd;
		for (const auto &File : Files) {
			cmdStr += ' ' + File;
		}
		cgi_debug("tar cmd = %s", cmdStr.c_str());
		system(cmdStr.c_str());
		sync();
	}

	ret = File_exists(tmpOutFile.c_str());
	if(!ret)
	{
		cgi_debug("tar file error(tmpOutFile)");
		deleteAllFileInPath(TAR_TEMP_FILEPATH);
		return ret;
	}

	ret = copyFile(tmpOutFile.c_str(), OutPath.c_str());
	if(!ret)
	{
		cgi_debug("copyFile error");
		deleteAllFileInPath(TAR_TEMP_FILEPATH);
		return ret;
	}

	ret = deleteAllFileInPath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("deleteAllFileInPath error");
		return ret;
	}

	ret = File_exists(outFileName);
	if(!ret)
	{
		cgi_debug("tar file error(outFileName)");
		return ret;
	}

	return true;

}

/*
 * 解压文件到指定路径
 * fileName:解压的文件名，需要包含路径，并且以.tar.gz结尾;	filePath:指定解压到的路径
 * checkFile:需要校验的文件。如果不传参checkFile, 则把解压后的所有文件cp到指定的目录。 如果有传参，只会把需要校验的文件cp到指定的目录
 */
bool Upg_File::unTarFile(const char * fileName, const char * filePath, vector<string> * pCheckFile)
{
	//size_t filePos;
	bool ret;
	if((nullptr == filePath) || (nullptr == fileName))
	{
		cgi_debug("Param is nullptr");
		return false;
	}
	string fileNameStr = fileName;
	string filePathStr = filePath;

	if((fileNameStr.find('/') == string::npos) || (fileNameStr.size() <= 7)
	  || (fileNameStr.substr(fileNameStr.size()-7)) == ".tar.gz")
	{
		cgi_debug("fileName error");
		return false;
	}
	ret = File_exists(fileName);
	if(!ret)
	{
		cgi_debug("file not exist(%s)", fileName);
		return false;
	}

	ret = checkAndCreatePath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}
	
	ret = deleteAllFileInPath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("deleteAllFileInPath error");
		return false;
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "%s %s -C %s", TAR_UNPRESS, fileName, TAR_TEMP_FILEPATH);
	cgi_debug("cmd = %s", cmd);
	system(cmd);
	sync();	

	if(filePathStr[filePathStr.size()-1] != '/')
	{
		filePathStr = filePathStr + '/';
	}
	ret = checkAndCreatePath(filePathStr.c_str());
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}

	if(nullptr == pCheckFile)
	{
		ret = copyAllFileInPath(TAR_TEMP_FILEPATH, filePathStr.c_str());
		if(!ret)
		{
			cgi_debug("copyFile error");
			deleteAllFileInPath(TAR_TEMP_FILEPATH);
			return false;
		}
	}
	else
	{
		string sigFile;
		vector<string> checkFiles = *pCheckFile;
		if(checkFiles.empty())
		{
			deleteAllFileInPath(TAR_TEMP_FILEPATH);
			return false;
		}
		for (auto &checkFile : checkFiles) {
			sigFile.clear();
			sigFile = "";
			if(string::npos == checkFile.find('/'))
				sigFile = TAR_TEMP_FILEPATH + checkFile;
			else
				sigFile = checkFile;
			
			if(!File_exists(sigFile.c_str()))
			{
				cgi_debug("check file not exist(%s)", sigFile.c_str());
				deleteAllFileInPath(TAR_TEMP_FILEPATH);
				return false;
			}
		}

		for (auto &checkFile : checkFiles) {
			sigFile.clear();
			sigFile = "";
			if(string::npos == checkFile.find('/'))
				sigFile = TAR_TEMP_FILEPATH + checkFile;
			else
				sigFile = checkFile;

			ret = copyFile(sigFile.c_str(), filePathStr.c_str());
			if(!ret)
			{
				cgi_debug("copyFile error(%s)", sigFile.c_str());
			}
		}
	}

	deleteAllFileInPath(TAR_TEMP_FILEPATH);
	return true;
}

/*
 * unZip解压文件到指定路径
 * fileName:需要解压的文件(包含路径);	filePath:指定解压到的路径
 * checkFile:需要校验的文件。如果不传参checkFile， 则把解压后的所有文件cp到指定的目录。 如果传参，只会把需要校验的文件cp到指定的目录
 */
bool Upg_File::unZipFile(const char * fileName, const char * filePath, vector<string> * pCheckFile)
{

	bool ret;
	if((nullptr == filePath) || (nullptr == fileName))
	{
		cgi_debug("Param is nullptr");
		return false;
	}
	string fileNameStr = fileName;
	string filePathStr = filePath;

	if((fileNameStr.find('/') == string::npos) || (fileNameStr.size() <=4)
	  || (fileNameStr.substr(fileNameStr.size()-4) == ".zip"))
	{
		cgi_debug("fileName error");
		return false;
	}
	ret = File_exists(fileName);
	if(!ret)
	{
		cgi_debug("file not exist(%s)", fileName);
		return false;
	}

	ret = checkAndCreatePath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		return false;
	}
	
	ret = deleteAllFileInPath(TAR_TEMP_FILEPATH);
	if(!ret)
	{
		cgi_debug("deleteAllFileInPath error");
		return false;
	}
	
	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "%s -o -d %s %s", UNZIP, TAR_TEMP_FILEPATH, fileName);
	cgi_debug("cmd = %s", cmd);
	system(cmd);
	sync();	

	if(filePathStr[filePathStr.size()-1] != '/')
	{
		filePathStr = filePathStr + '/';
	}
	ret = checkAndCreatePath(filePathStr.c_str());
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error");
		deleteAllFileInPath(TAR_TEMP_FILEPATH);
		return false;
	}

	if(nullptr == pCheckFile)
	{
		ret = copyAllFileInPath(TAR_TEMP_FILEPATH, filePathStr.c_str());
		if(!ret)
		{
			cgi_debug("copyFile error");
			deleteAllFileInPath(TAR_TEMP_FILEPATH);
			return false;
		}
	}
	else
	{
		string sigFile;
		vector<string> checkFiles = *pCheckFile;
		if(checkFiles.empty())
		{
			deleteAllFileInPath(TAR_TEMP_FILEPATH);
			return false;
		}
		for (auto &checkFile : checkFiles) {
			sigFile.clear();
			sigFile = "";
			if(string::npos == checkFile.find('/'))
				sigFile = TAR_TEMP_FILEPATH + checkFile;
			else
				sigFile = checkFile;
			
			if(!File_exists(sigFile.c_str()))
			{
				cgi_debug("check file not exist(%s)", sigFile.c_str());
				deleteAllFileInPath(TAR_TEMP_FILEPATH);
				return false;
			}
		}

		for (auto &checkFile : checkFiles) {
			sigFile.clear();
			sigFile = "";
			if(string::npos == checkFile.find('/'))
				sigFile = TAR_TEMP_FILEPATH + checkFile;
			else
				sigFile = checkFile;

			ret = copyFile(sigFile.c_str(), filePathStr.c_str());
			if(!ret)
			{
				cgi_debug("copyFile error(%s)", sigFile.c_str());
			}
		}
	}

	deleteAllFileInPath(TAR_TEMP_FILEPATH);
	return true;
}


/*
 * 获取某目录下的所有文件名
 *
 */
bool Upg_File::getAllFileInPath(const char * filePath, vector<string> &fileNames)
{
	bool ret;
	if(nullptr == filePath)
	{
		cgi_debug("Param is nullptr");
		return false;
	}

	ret = File_isPath(filePath);
	if(!ret)
	{
		cgi_debug("%s is not Path", filePath);
		return false;
	}

	char cmd[CMD_LEN] = {0};
	char result[SZ_1M] = {0};
	snprintf(cmd, CMD_LEN, "ls %s", filePath);
	ret = File_Shell_exec(cmd, result, sizeof(result));
	if(!ret)
	{
		cgi_debug("File_Shell_exec error");
		return false;
	}

	//UPG_PRINT("result = %s", result);
	fileNames.clear();
	BWStr::split_ex(fileNames, result, "\n", false);

    return !fileNames.empty();

}

bool Upg_File::File_Shell_exec(const char* cmdline, char* out, size_t out_len)
{
    FILE *pipe;
    char buf[1024] = {0};
    char result[SZ_1M];
    memset(result, 0, sizeof(result));
    char* p = result;
	cgi_debug("cmd = %s", cmdline);
    if ( (pipe = popen(cmdline, "r")) != nullptr )
    {
        while ( !feof(pipe) && !ferror(pipe) )
        {
            memset(buf, 0, sizeof(buf));
            size_t n = fread(buf, 1, 1024, pipe);
            snprintf(p, sizeof(result)-strlen(result), "%s", buf);
            p += n;
        }
        pclose(pipe);
    }

    if (out) {
    	snprintf(out, out_len, "%s", result);
    }
	return true;
}

    /*	加密	*/
    bool Upg_File::bw_comm_Encrypt(const char *infile,const char *outfile,const char *password)
    {
        char cmd[1024] = {0};

        if((infile == nullptr)||(outfile== nullptr)||(password == nullptr))
            return false;
        snprintf(cmd,sizeof(cmd),"openssl enc -p -des3 -a -pass pass:%s -in %s -out %s",password,infile,outfile);
        cgi_debug("encrypt cmd = %s", cmd);
        system(cmd);

        return true;
    }

/*  文件解密	*/
bool Upg_File::File_UnEncrypt(const char *infile,const char *outfile,const char *password)
{
	bool ret = true;
	char cmd[1024] = {0};
	char result[1024]={0};
	char * tmp1 = nullptr, *tmp2 = nullptr, *tmp3 = nullptr;
	if((infile == nullptr)||(outfile== nullptr)||(password == nullptr))
		return false;
	
	snprintf(cmd,sizeof(cmd),"openssl enc -d -des3 -a -pass pass:%s -in %s -out %s 2>&1",password,infile,outfile);
	cgi_debug("unencrypt cmd = %s", cmd);

	File_Shell_exec(cmd, result, sizeof(result));
	cgi_debug("====>result = %s", result);
	
	tmp1 = strstr(result,ENCRYPT_TAG);
	tmp2 = strstr(result,ERROR_READING);
	tmp3 = strstr(result,NO_SUCH_FILE);
	if((tmp1 != nullptr) || (tmp2 != nullptr) || (tmp3 != nullptr))
	{
		ret = false;
	}
	
	return ret;
}

/*
 *	获取文件大小
 *	出错返回-1， 成功返回文件大小
 */
S32 Upg_File::File_size(const char* fileName) 
{
	struct stat buf;
	if((nullptr == fileName) || (stat(fileName, &buf) < 0))
	{
		return -1;
	}

	return (S32)buf.st_size;
}

/*
 * 文件是否存在
 * 0: not exist
 * 1: exist
 */
bool Upg_File::File_exists(const char* fileName) 
{
	struct stat sb;
	return stat(fileName, &sb) == 0;
}

/*
 * 文件是否有可执行权限
 * false: not excecutable
 * true: excecutable
 */
bool Upg_File::File_isExcecutable(const char* fileName)
{
	if(fileName == nullptr)
	{
		return false;
	}
    return access(fileName, X_OK) == 0;

}

/*
 * 功能:更改权限->可执行权限
 * false:更改失败;	true:更改成功
 */
bool Upg_File::File_becomeExcecutable(const char* fileName)
{
	bool ret;
	ret = File_isExcecutable(fileName);
	if(ret)
		return ret;

	char cmd[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "chmod +x %s", fileName);
	cgi_debug("cmd = %s", cmd);
	system(cmd);
	sync();

	return File_isExcecutable(fileName);
}

/*
 * 判断是否是目录
 */
bool Upg_File::File_isPath(const char * filePath)
{
	if(nullptr == filePath)
	{
		cgi_debug("param nullptr");
		return false;
	}

	struct stat buf;
	stat(filePath, &buf);
	if(S_ISDIR(buf.st_mode))
	{
		return true;
	}

	return false;
}

/*
 * 功能：文件移动到指定路径
 * srcFileName: 源文件名。 dstFilePath:需要移动到的路径(不能是文件名)。
 * isForced: true, 强制移动; false:如果目的路径有同名文件则不移动,并返回ERROR
 */
bool Upg_File::File_move(const char* srcFileName, const char *dstFilePath, bool isForced)
{
	bool ret;

	if((nullptr == srcFileName) || (nullptr == dstFilePath))
	{
		cgi_debug("param nullptr");
		return false;
	}
	
	ret = File_exists(srcFileName);
	if(!ret)
	{
		cgi_debug("file not exist(%s)", srcFileName);
		return ret;
	}
	
	string dstPathStr = dstFilePath;
	if(dstFilePath[dstPathStr.size()-1] != '/')
	{
		dstPathStr = dstPathStr + '/';
	}
	
	ret = checkAndCreatePath(dstPathStr.c_str());
	if(!ret)
	{
		cgi_debug("checkAndCreatePath error(%s)", dstPathStr.c_str());
		return ret;
	}

	size_t fnamePos;
	string onlyNameStr = srcFileName;
	fnamePos = onlyNameStr.rfind('/');
	if(fnamePos != string::npos)
	{
		onlyNameStr = onlyNameStr.substr(fnamePos+1);
	}
	string dstFileName = dstPathStr +onlyNameStr;

	char cmd[CMD_LEN] = {0};
	if(isForced)
	{
		snprintf(cmd, sizeof(cmd), "mv -vf %s %s", srcFileName, dstPathStr.c_str());
		cgi_debug("mv cmd = %s", cmd);
		system(cmd);
		sync();
		return File_exists(dstFileName.c_str());
	}
	else
	{
		if(File_exists(dstFileName.c_str()))
		{
			cgi_debug("(unforced mv)dst file exist(%s)", dstFileName.c_str());
			return false;
		}
		snprintf(cmd, sizeof(cmd), "mv -v %s %s", srcFileName, dstPathStr.c_str());
		cgi_debug("mv cmd = %s", cmd);
		system(cmd);
		sync();
		return File_exists(dstFileName.c_str());
	}
}

/*
 * 功能: 更改文件名(仅限同一个目录), 移动文件请使用File_move
 * srcFileName: 需要改名的文件。 changeName:改成的文件名,不能含有路径
 * isForced: true:强制改名(可能会覆盖该路径下的同名文件); false:有同名文件则直接返回ERROR
 */
bool Upg_File::File_nameChange(const char* srcFileName, const char *changeName, bool isForced)
{
	bool ret;

	if((nullptr == srcFileName) || (nullptr == changeName))
	{
		cgi_debug("param nullptr");
		return false;
	}

	string changeNameStr = changeName;
	if(changeNameStr.find('/') != string::npos)
	{
		cgi_debug("name error(%s)", changeName);
		return false;
	}
	ret = File_exists(srcFileName);
	if(!ret)
	{
		cgi_debug("file not exist(%s)", srcFileName);
		return ret;
	}

	size_t fnamePos;
	string srcFileNameStr = srcFileName;
	string filePath, onlyNameStr, dstFile;
	fnamePos = onlyNameStr.rfind('/');
	if(fnamePos != string::npos)
	{
		filePath = srcFileNameStr.substr(0, fnamePos+1);
		onlyNameStr = srcFileNameStr.substr(fnamePos+1);
	}
	
	if(filePath.empty())
		dstFile = changeNameStr;
	else
	{
		ret = checkAndCreatePath(filePath.c_str());
		if(!ret)
		{
			cgi_debug("checkAndCreatePath error (%s)", filePath.c_str());
			return ret;
		}
		dstFile = filePath + changeNameStr;
	}
	
	char cmd[CMD_LEN] = {0};
	if(isForced)
	{
		snprintf(cmd, sizeof(cmd), "mv -vf %s %s", srcFileName, dstFile.c_str());
		cgi_debug("mv cmd = %s", cmd);
		system(cmd);
		sync();
		return File_exists(dstFile.c_str());
	}
	else
	{
		if(File_exists(dstFile.c_str()))
		{
			cgi_debug("(unforced mv)dst file exist(%s)", dstFile.c_str());
			return false;
		}
		snprintf(cmd, sizeof(cmd), "mv -v %s %s", srcFileName, dstFile.c_str());
		cgi_debug("mv cmd = %s", cmd);
		system(cmd);
		sync();
		return File_exists(dstFile.c_str());
	}
}

bool Upg_File::writePipe(const char * content, int len, const char * pipeName)
{
	bool ret;
    int res;
	ret = File_exists(pipeName);
	if(!ret)
	{
		cgi_debug("%s pipe not exist, build now", pipeName);
		res = mkfifo(pipeName, 0777);
		if( 0 != res)
		{
			cgi_debug("create pipe(%s)",pipeName);
			return false;
		}
	}

//	string tmpStr = pipeName;
//	size_t fnPos = tmpStr.rfind('/');
//	if(fnPos == string::npos)
//    {
//	    UPG_PRINT("pipeName error : should have path");
//	    return false;
//    }
//	tmpStr = tmpStr.substr(0, fnPos);
//	ret = checkAndCreatePath(tmpStr.c_str());
//	if(!ret)
//    {
//	    UPG_PRINT("checkAndCreatePath ERROR : %s", tmpStr.c_str());
//	    return false;
//    }
    //int pipe_fd = open(pipeName, O_WRONLY | O_NONBLOCK);
	int pipe_fd = open(pipeName, O_WRONLY);
	if(-1 == pipe_fd)
	{
		cgi_debug("open pipe error(pipeFile:%s)", pipeName);
		return false;
	}

	res = write(pipe_fd, content, len);
	if(-1 == res)
	{
		cgi_debug("write pipe error");
		close(pipe_fd);
		return false;
	}

	close(pipe_fd);
	return true;
}

/*	
 *	功能：从字符串中获取pid的值
 *	str: 是通过接口progressIsRun 获取的字符串
 */
void Upg_File::getPid(string & str, vector<U32> &pid)
{
	pid.clear();
	if (str.empty()) {
		cgi_debug("PARAM STRING IS EMPTY");
		return;
	}
	cgi_debug("str = \n%s", str.c_str());

	char cmd[CMD_LEN] = {0};
	char result[CMD_LEN] = {0};
	snprintf(cmd, CMD_LEN, "ps -ef");
	if(!File_Shell_exec(cmd, result, CMD_LEN)){
		cgi_debug("shell exec error");
		return;
	}
	string judgeStr = result;
	size_t pos;
	pos = judgeStr.find('\n');
	if(pos == string::npos)
	{
		cgi_debug("judge pid error");
		return;
	}
	judgeStr = judgeStr.substr(0, pos);
	vector<string> Array;
	BWStr::split_ex(Array, judgeStr, " ", false);
	if(Array.size() < 3){
		cgi_debug("judge pid error");
		return;
	}
	U32 pidPos = 0;
	auto iter = Array.begin();
	for(; iter != Array.end(); iter++)
	{
		if(*iter == "PID")
			break;
		pidPos++;
	}
	if(iter == Array.end() || pidPos >= 5){
		cgi_debug("judge pid error");
		return;
	}
	string sigProcess;
	while (true) {
		sigProcess.clear();
		pos = str.find('\n');
		if (pos == string::npos)
			break;
		sigProcess = str.substr(0, pos);
		if (sigProcess.size() < 5)
			break;
		BWStr::split(Array, sigProcess, " ", false);
		if (Array.size() < pidPos)
			break;
		int sigPid = atoi(Array[pidPos].c_str());
		//不能转换成 int 或者 nptr为空字符串，那么将返回 0
		if (sigPid == 0)
			continue;
		pid.push_back((U32)sigPid);
		str = str.substr(pos + 1);
	}
}

/*	
 *	功能：判断进程是否存在, 并得到进程id值
 *	pid:pid的值
 *	progressInfo: ps -ef 查询到的相关信息会保存在字符串中(用于解析pid值)
 *	progressName:进程名
 *  param:进程运行时带的参数，默认为nullptr。 param默认以'-'开头，如果不一'-'开头，会自动补上
 *		   例：param 为 monitor，则会自动补全成 -monitor
 */
bool Upg_File::progressIsRun(const char * progressName, string & progressInfo, const char * param)
{
	if(progressName == nullptr)
	{
		cgi_debug("PARAM nullptr");
		return false;
	}
	
	bool ret;
	char cmd[CMD_LEN] = {0};
	char * result = new char[SZ_1M];
	memset(result, 0, SZ_1M);
//	char result[SZ_16K] = {0};
	snprintf(cmd, CMD_LEN, "ps -ef | grep %s | grep -v grep", progressName);
	ret = File_Shell_exec(cmd, result, SZ_1M);
	if(!ret)
	{
		cgi_debug("shell exec error");
		SAFE_DELETE_ARRAY(result);
		return ret;
	}

	string resultStr = result;
	cgi_debug("result = %s", resultStr.c_str());
	SAFE_DELETE_ARRAY(result);
	if(resultStr.empty())
		return false;

	size_t pos;
	progressInfo.clear();
	string tmpStr = progressName;
	pos = tmpStr.rfind('/');
	if(pos != string::npos)
        tmpStr = tmpStr.substr(pos);

	if(nullptr == param) 
	{
		if(resultStr.find(tmpStr) != string::npos)
		{
			progressInfo = move(resultStr);
			return true;
		}
		else
			return false;
	}

	if(param[0] == '-')
		tmpStr = tmpStr + ' ' + param;
	else
		tmpStr = tmpStr + " -" + param;
	cgi_debug("find key = %s", tmpStr.c_str());
	string sigInfo;
	pos = resultStr.find(tmpStr);
	if(pos == string::npos)
		return false;

	while(true)
	{
		pos = resultStr.find('\n');
		if(pos == string::npos)
			break;
		sigInfo = resultStr.substr(0, pos+1);
		if(sigInfo.find(tmpStr) != string::npos)
			progressInfo += sigInfo;
		resultStr = resultStr.substr(pos+1);
		if(resultStr.size() < 5)
			break;
	}
	return true;
}

bool Upg_File::stopProgress(const char *progressName, vector<string> * pParam)
{
	int tryNum = 3;
	if(progressName == nullptr)
	{
		cgi_debug("PARAM nullptr");
		return false;
	}
	
	vector<U32>pid;
	string processInfo;
	if(nullptr == pParam)
	{
		while(tryNum-- >0)
		{
			if(!progressIsRun(progressName, processInfo))
			{
				cgi_debug("PROGRESS HAS ALREADY STOP : %s", progressName);
				return true;
			}
			getPid(processInfo, pid);
			for (unsigned int i : pid) {
				char cmd[CMD_LEN] = {0};
				snprintf(cmd, CMD_LEN, "kill -9 %d", i);
				cgi_debug("stop cmd = %s",cmd);
				system(cmd);
				sync();
			}
			if(!progressIsRun(progressName, processInfo))
				return true;

			usleep(10000);
		}
	}
	else
	{
		vector<string>Param = *pParam;
		if(Param.empty())
		{
			cgi_debug("Param is empty");
			return false;
		}
		bool *isrun = new bool[Param.size()];
		memset(isrun, true, sizeof(bool)*Param.size());

		char cmd[CMD_LEN] = {0};
		while(tryNum-- >0)
		{
			U32 runIdx;			
			for(runIdx = 0; runIdx < Param.size(); runIdx++)
			{
				if((!isrun[runIdx]) || !progressIsRun(progressName, processInfo, Param[runIdx].c_str()))
				{
					cgi_debug("file already stop : %s %s", progressName, Param[runIdx].c_str());
					isrun[runIdx] = false;
					continue;
				}
				getPid(processInfo, pid);
				for (unsigned int i : pid) {
					memset(cmd, 0, CMD_LEN);
					snprintf(cmd, CMD_LEN, "kill -9 %d", i);
					cgi_debug("stop cmd = %s",cmd);
					system(cmd);
					sync();
				}
				if(!progressIsRun(progressName, processInfo, Param[runIdx].c_str()))
					isrun[runIdx] = false;
			}
			for(runIdx = 0; runIdx < Param.size(); runIdx++)
			{
				if(isrun[runIdx])
				{
					cgi_debug("stop process error : %s %s", progressName, Param[runIdx].c_str());
					break;
				}
			}
			if(runIdx >= Param.size())
			{
				SAFE_DELETE_ARRAY(isrun);
				return true;
			}
			usleep(10000);
		}
		SAFE_DELETE_ARRAY(isrun);
	}
	return false;
}

bool Upg_File::startProgress(const char *progressName, const char *Param)
{
	int tryNum = 3;
	if (progressName == NULL) {
		cgi_debug("PARAM NULL");
		return false;
	}

	char cmd[CMD_LEN] = {0};
	string uselessStr;
	while (tryNum-- > 0)
	{
		if (progressIsRun(progressName, uselessStr, Param)) {
			cgi_debug("progress already runned:%s", progressName);
			return true;
		}

		if(Param){
			snprintf(cmd, CMD_LEN, "%s %s &\n", progressName, Param);
		} else {
			snprintf(cmd, CMD_LEN, "%s &\n", progressName);
		}
		cgi_debug("start cmd = %s", cmd);
		system(cmd);
		sync();
		usleep(200000);
		if (progressIsRun(progressName, uselessStr, Param))
			return true;

		usleep(10000);
	}
	return false;
}
	/*
     * 判断系统是否是大端字节序
     * true:是大端 false:是小端
     */
	bool Upg_File::isBigEndian()
	{
		union JUDGE{
			int i;
			char c;
		};
		JUDGE judge;
		judge.i = 1;

		return judge.c != 1;
	}

}/*	namespace	*/
